<!--对话框组件：配置字段以创建数据表-->
<template>
  <div>
    <!--按钮-->
    <a-button @click="openModal">
      <template #icon>
        <icon-plus />
      </template>
      创建表
    </a-button>

    <!--对话框-->
    <a-modal
      :visible="visible"
      :width="1200"
      title="创建数据表"
      @ok="validateForm"
      @cancel="closeModal"
    >
      <!--表基本信息填写-->
      <a-typography-title :heading="6">基本信息</a-typography-title>
      <a-form ref="formRef" :model="form" layout="vertical" :rules="rules">
        <a-row :gutter="24">
          <a-col :span="8">
            <a-form-item label="表名" field="tableName">
              <a-input v-model="form.tableName" placeholder="请输入表名" />
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item label="表描述" field="tableComment">
              <a-input v-model="form.tableComment" placeholder="请输入表描述" />
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item label="数据源" field="dataSourceConfigId">
              <a-select
                v-model="form.dataSourceConfigId"
                :options="dataSourceList"
                :field-names="{
                  value: 'id',
                  label: 'name',
                }"
                :loading="dataSourceLoading"
                placeholder="请选择数据源"
              />
            </a-form-item>
          </a-col>
        </a-row>
      </a-form>

      <!--表字段定义和索引定义-->
      <a-tabs type="card-gutter">
        <!--tab: 字段定义-->
        <a-tab-pane key="1" title="字段">
          <a-space style="margin-bottom: 7px">
            <a-button type="primary" @click="addField">
              <template #icon>
                <icon-plus />
              </template>
              添加字段
            </a-button>

            <!--按钮：删除-->
            <a-button
              :disabled="selectedFields.length === 0"
              @click="removeField"
            >
              <template #icon>
                <icon-minus />
              </template>
              删除
            </a-button>

            <!--checkbox；是否逻辑删除-->
            <a-checkbox v-model="hasDelete">逻辑删除</a-checkbox>

            <!--checkbox；是否使用乐观锁-->
            <a-checkbox v-model="hasVersion">使用乐观锁</a-checkbox>
          </a-space>

          <!--表格：表字段-->
          <a-table
            v-model:selected-keys="selectedFields"
            :columns="COLUMNS_FIELD"
            :data="fieldList"
            :scroll="{ x: 1000 }"
            row-key="id"
            :row-selection="rowSelection"
          >
            <!--插槽（通用）：多选框-->
            <template #checkBox="{ rowIndex, column }">
              <a-checkbox
                v-model="fieldList[rowIndex][column.dataIndex]"
                :disabled="fieldList[rowIndex].disabled"
              />
            </template>

            <!--插槽（通用）：普通输入框-->
            <template #inputBox="{ rowIndex, column }">
              <a-input
                v-model="fieldList[rowIndex][column.dataIndex]"
                :disabled="fieldList[rowIndex].disabled"
              />
            </template>

            <!--插槽（通用）：数字输入框-->
            <template #numberBox="{ rowIndex, column }">
              <a-input-number
                v-model="fieldList[rowIndex][column.dataIndex]"
                :disabled="fieldList[rowIndex].disabled"
              />
            </template>

            <!--插槽：字段类型-->
            <template #dataType="{ rowIndex }">
              <a-select
                v-model="fieldList[rowIndex].dataType"
                :disabled="fieldList[rowIndex].disabled"
                :options="dataTypeOptions"
              />
            </template>
          </a-table>
        </a-tab-pane>

        <!--tab: 索引定义-->
        <a-tab-pane key="2" title="索引">
          <a-space style="margin-bottom: 7px">
            <a-button type="primary" @click="addIndex">
              <template #icon>
                <icon-plus />
              </template>
              添加索引
            </a-button>
            <a-button
              :disabled="selectedIndexes.length === 0"
              @click="removeIndex"
            >
              <template #icon>
                <icon-minus />
              </template>
              删除
            </a-button>
          </a-space>

          <!--表格：索引-->
          <a-table
            v-model:selected-keys="selectedIndexes"
            :columns="COLUMNS_INDEX"
            :data="indexList"
            :scroll="{ x: 1000 }"
            row-key="id"
            :row-selection="rowSelection"
          >
            <!--插槽：索引列表头提示-->
            <template #indexColumnsTitle>
              索引列
              <a-tooltip
                content="有多个索引列时请使用英文逗号分隔，如：user,name"
              >
                <icon-question-circle-fill />
              </a-tooltip>
            </template>

            <!--插槽（通用）：多选框-->
            <template #checkBox="{ rowIndex, column }">
              <a-checkbox v-model="indexList[rowIndex][column.dataIndex]" />
            </template>

            <!--插槽（通用）：普通输入框-->
            <template #inputBox="{ rowIndex, column }">
              <a-input v-model="indexList[rowIndex][column.dataIndex]" />
            </template>
          </a-table>
        </a-tab-pane>
      </a-tabs>
    </a-modal>
  </div>
</template>

<script setup lang="ts" name="TableCreateModal">
  import { ref, reactive, computed } from 'vue';
  import {
    TableColumnData,
    TableRowSelection,
    Message,
  } from '@arco-design/web-vue';
  import { DataSourceRecord } from '@/api/infrastructure/model/dataSourceConfigModel';
  import { queryDataSourceRecord } from '@/api/infrastructure/data-source-config';
  import {
    TableFieldRecord,
    TableIndexRecord,
  } from '@/api/infrastructure/model/codegenModel';
  import { createTableRecord } from '@/api/infrastructure/codegen';

  const emits = defineEmits(['afterSubmit']);
  const visible = ref<boolean>(false);
  const openModal = () => {
    listDataSource();
    initForm();
    initFields();
    visible.value = true;
  };
  const closeModal = () => {
    visible.value = false;
    // 清空基础信息定义
    formRef.value.resetFields();
    // 清空字段定义
    selectedFields.value = [];
    editablefieldList.value = [];
    hasDelete.value = false;
    hasVersion.value = false;
    // 清空索引定义
    indexList.value = [];
    selectedIndexes.value = [];
  };

  const dataSourceList = ref<DataSourceRecord[]>([]);
  const dataSourceLoading = ref<boolean>(false);
  const listDataSource = async () => {
    dataSourceLoading.value = true;
    try {
      const { data } = await queryDataSourceRecord();
      dataSourceList.value = data;
    } finally {
      dataSourceLoading.value = false;
    }
  };
  // 逻辑删除标志，为true时有字段
  const hasDelete = ref<boolean>(false);
  const hasVersion = ref<boolean>(false);
  const generateForm = () => {
    return {
      tableName: '',
      tableComment: '',
      dataSourceConfigId: '',
    };
  };
  const formRef = ref<any>();
  const form = ref(generateForm());
  const initForm = () => {
    form.value = generateForm();
  };
  const rules = {
    tableName: [{ required: true, message: '请输入表名' }],
    tableComment: [{ required: true, message: '请输入表描述' }],
    dataSourceConfigId: [{ required: true, message: '请选择数据源' }],
  };

  const rowSelection = reactive<TableRowSelection>({
    type: 'checkbox',
    showCheckedAll: true,
    onlyCurrent: false,
  });
  // eslint-disable-next-line no-shadow
  enum DataTypes {
    varchar = 'VARCHAR',
    tinyint = 'TINYINT',
    int = 'INTEGER',
    bigint = 'BIGINT',
    double = 'DOUBLE', // 有小数
    date = 'DATE', // 无长度
    datetime = 'DATETIME', // 无长度
    decimal = 'DECIMAL', // 有小数
    bit = 'BOOLEAN',
  }
  const dataTypeOptions = [
    { label: 'varchar', value: DataTypes.varchar },
    { label: 'tinyint', value: DataTypes.tinyint },
    { label: 'int', value: DataTypes.int },
    { label: 'bigint', value: DataTypes.bigint },
    { label: 'double', value: DataTypes.double },
    { label: 'date', value: DataTypes.date },
    { label: 'datetime', value: DataTypes.datetime },
    { label: 'decimal', value: DataTypes.decimal },
    { label: 'bit', value: DataTypes.bit },
  ];
  const selectedFields = ref<string[]>([]);
  const fieldList = computed(() => {
    return [...editablefieldList.value, ...disabledfieldList.value];
  });
  // 可编辑的字段
  const editablefieldList = ref<any[]>([]);
  // 不可编辑的字段：delete和version
  const disabledfieldList = computed(() => {
    const list = [];
    if (hasDelete.value) {
      list.push({
        id: Math.random().toString(16).slice(2),
        columnName: 'deleted',
        columnComment: '是否删除',
        dataType: DataTypes.bit,
        columnLength: 1,
        nullable: false,
        primaryKey: false,
        autoIncrement: false,
        disabled: true,
      });
    }
    if (hasVersion.value) {
      list.push({
        id: Math.random().toString(16).slice(2),
        columnName: 'version',
        columnComment: '乐观锁',
        columnLength: 16,
        dataType: DataTypes.int,
        nullable: false,
        primaryKey: false,
        autoIncrement: false,
        disabled: true,
      });
    }
    return list;
  });
  const initFields = () => {
    editablefieldList.value = [
      {
        id: Math.random().toString(16).slice(2),
        columnName: 'id',
        columnComment: '主键',
        columnLength: 20,
        dataType: DataTypes.bigint,
        nullable: false,
        primaryKey: true,
        autoIncrement: true,
      },
      {
        id: Math.random().toString(16).slice(2),
        columnName: 'creator',
        columnComment: '创建者',
        columnLength: 64,
        dataType: DataTypes.varchar,
        nullable: true,
        primaryKey: false,
        autoIncrement: false,
      },
      {
        id: Math.random().toString(16).slice(2),
        columnName: 'create_time',
        columnComment: '创建时间',
        columnLength: 0,
        dataType: DataTypes.datetime,
        nullable: false,
        primaryKey: false,
        autoIncrement: false,
      },
      {
        id: Math.random().toString(16).slice(2),
        columnName: 'updater',
        columnComment: '更新者',
        columnLength: 64,
        dataType: DataTypes.varchar,
        nullable: true,
        primaryKey: false,
        autoIncrement: false,
      },
      {
        id: Math.random().toString(16).slice(2),
        columnName: 'update_time',
        columnComment: '更新时间',
        columnLength: 0,
        dataType: DataTypes.datetime,
        nullable: false,
        primaryKey: false,
        autoIncrement: false,
      },
      {
        id: Math.random().toString(16).slice(2),
        columnName: 'update_ip',
        columnComment: '更新ip',
        columnLength: 32,
        dataType: DataTypes.varchar,
        nullable: true,
        primaryKey: false,
        autoIncrement: false,
      },
    ];
  };
  const COLUMNS_FIELD: TableColumnData[] = [
    {
      title: '序号',
      dataIndex: 'index',
      width: 70,
      fixed: 'left',
      render: ({ rowIndex }) => rowIndex + 1,
    },
    {
      title: '字段名称',
      dataIndex: 'columnName',
      width: 150,
      slotName: 'inputBox',
    },
    {
      title: '字段描述',
      dataIndex: 'columnComment',
      width: 150,
      slotName: 'inputBox',
    },
    {
      title: '字段长度',
      dataIndex: 'columnLength',
      slotName: 'numberBox',
      width: 150,
    },
    {
      title: '小数点',
      dataIndex: 'decimalPoint',
      slotName: 'numberBox',
      width: 150,
    },
    {
      title: '默认值',
      dataIndex: 'defaultValue',
      width: 150,
      slotName: 'inputBox',
    },
    {
      title: '字段类型',
      dataIndex: 'dataType',
      slotName: 'dataType',
      width: 150,
    },
    {
      title: '是否主键',
      dataIndex: 'primaryKey',
      width: 100,
      align: 'center',
      slotName: 'checkBox',
    },
    {
      title: '允许空值',
      dataIndex: 'nullable',
      width: 100,
      align: 'center',
      slotName: 'checkBox',
    },
    {
      title: '是否自增',
      dataIndex: 'autoIncrement',
      width: 100,
      align: 'center',
      slotName: 'checkBox',
    },
  ];
  const addField = () => {
    const newRow = {
      id: new Date().getTime(),
      columnName: '',
      columnComment: '',
      columnLength: 0,
      dataType: '',
      decimalPoint: 0,
      defaultValue: '',
      nullable: false,
      primaryKey: false,
      autoIncrement: false,
    };
    editablefieldList.value = [...editablefieldList.value, newRow];
  };
  const removeField = () => {
    const newList = editablefieldList.value.filter(
      (elem) => !selectedFields.value.includes(elem.id)
    );
    editablefieldList.value = newList;
    selectedFields.value = [];
  };

  const selectedIndexes = ref<string[]>([]);
  const indexList = ref<any[]>([]);
  const COLUMNS_INDEX: TableColumnData[] = [
    {
      title: '序号',
      dataIndex: 'index',
      width: 70,
      fixed: 'left',
      render: ({ rowIndex }) => rowIndex + 1,
    },
    {
      title: '索引名',
      dataIndex: 'indexName',
      slotName: 'inputBox',
      width: 150,
    },
    {
      dataIndex: 'indexColumns',
      width: 200,
      slotName: 'inputBox',
      titleSlotName: 'indexColumnsTitle',
    },
    { title: '索引注释', dataIndex: 'indexComment', slotName: 'inputBox' },
    {
      title: '是否唯一索引',
      dataIndex: 'unique',
      align: 'center',
      width: 150,
      slotName: 'checkBox',
    },
  ];
  const addIndex = () => {
    const newRow = {
      id: new Date().getTime(),
      indexName: '',
      indexColumns: '',
      indexComment: '',
      unique: false,
    };
    indexList.value = [...indexList.value, newRow];
  };
  const removeIndex = () => {
    const newList = indexList.value.filter(
      (elem) => !selectedIndexes.value.includes(elem.id)
    );
    indexList.value = newList;
    selectedIndexes.value = [];
  };

  const collectField = (elem: TableFieldRecord) => {
    // id是要删除的所以。
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const { id, decimalPoint, dataType, ...rest } = elem;
    if (DataTypes.double === dataType || DataTypes.decimal === dataType) {
      // 具有小数
      return {
        ...rest,
        decimalPoint,
        dataType,
      };
    }
    return {
      ...rest,
      dataType,
    };
  };
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const collectIndex = ({ id, ...rest }: TableIndexRecord) => {
    return rest;
  };
  // 收集数据提交表单，并告知父组件
  const submitForm = async () => {
    const reqdata = {
      ...form.value,
      columnList: fieldList.value.map((elem) => collectField(elem)),
      indexList: indexList.value.map((elem) => collectIndex(elem)),
    };
    try {
      await createTableRecord(reqdata);
      Message.success('创建成功');
    } finally {
      closeModal();
      emits('afterSubmit');
    }
  };

  // 提交表单前：校验字段是否填写完成
  const validateForm = async () => {
    const errors = await formRef.value.validate();
    if (!errors) {
      submitForm();
    }
  };
</script>
